package com.fezs.web.mvc.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.fezs.common.constants.SecurityConstant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zhukai
 * @since 2022/8/18
 */
public class JwtUtils {

    private static String secret = "security";

    public static void setJwtSecret(String secret) {
        JwtUtils.secret = secret;
    }

    /**
     * 从数据声明生成令牌
     *
     * @return 令牌
     */
    public static String createToken(Long userId, String deviceType) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("deviceType", deviceType);
        // 混入随机字符串，防止每次生成的 token 都是一样的
        claims.put("rd", RandomUtil.randomString(4));
        return createToken(claims);
    }

    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    public static String createToken(Map<String, Object> claims) {
        return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static Claims parseToken(String token) {
        return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
    }

    /**
     * 根据令牌获取用户ID
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static Long getUserId(String token) {
        Claims claims = parseToken(token);
        return getLong(claims, SecurityConstant.USER_ID);
    }

    /**
     * 根据身份信息获取用户ID
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static Long getUserId(Claims claims) {
        return getLong(claims, SecurityConstant.USER_ID);
    }

    /**
     * 根据令牌获取用户名
     *
     * @param token 令牌
     * @return 用户名
     */
    public static String getDeviceType(String token) {
        Claims claims = parseToken(token);
        return getStr(claims, SecurityConstant.DEVICE_TYPE);
    }

    /**
     * 根据身份信息获取用户名
     *
     * @param claims 身份信息
     * @return 用户名
     */
    public static String getDeviceType(Claims claims) {
        return getStr(claims, SecurityConstant.DEVICE_TYPE);
    }

    /**
     * 根据身份信息获取键值
     *
     * @param claims 身份信息
     * @param key    键
     * @return 值
     */
    public static String getStr(Claims claims, String key) {
        return Convert.toStr(claims.get(key), "");
    }

    /**
     * 根据身份信息获取键值
     *
     * @param claims 身份信息
     * @param key    键
     * @return 值
     */
    public static Long getLong(Claims claims, String key) {
        return Convert.toLong(claims.get(key));
    }

}
